# Z80 Test: NMI during EI

This is a hardware/software project created to test the behaviour of an actual Z80 when an NMI is triggered during the execution of an EI instruction. This condition causes a short between Vcc and Vss for a short time, and it's not clear what the intermediate value on this line should be, causing several die-level Z80 emulators to report a very surprising result. The whole story can be read here directly from its discoverer: https://github.com/hoglet67/Z80Decoder/wiki/NMI-during-EI-Anomaly

In a nutshell, according to the simulation, when triggering the NMI before the last cycle of an EI instruction, the IFF2 register does not get set; consequently, when using RETN to return from the NMI, interrupts are not enabled despite having just executed an EI. However, in a different simulation interrupts are properly enabled. This piqued my curiosity as to whether real hardware behaves one way or another, which is why I started this project.

## Hardware

The hardware is set up so that an NMI is triggered when /M1 = 0 and A9 = 1, similar to a hardware breakpoint but less specific. NMI is armed on the falling edge of the pin, and is detected at the end of the instruction, so this setup allows triggering the NMI right after an instruction that starts at 200h.

There's no RAM, only ROM. I used a Winbond W27C512 64KBx8 EEPROM, but only the first 1KB of it is actually mapped; the rest of the Z80 address space is mirrors of that 1KB space. This was done just to save wiring on the breadboard used to build it.

To test whether interrupts are enabled, the /INT line is permanently active, therefore an interrupt should be triggered whenever IFF1 is on, but the software carefully chooses the right time to allow this to happen.

The output is done via a LED, which is active when /RFSH is active and A10 is on. This permits activation of the LED by manipulating bit 2 of the I register, but causes the bright of the LED to be half its normal bright or less. No big deal, as long as the LED can be seen turning on and off.

Since this test affects a circuit that is effectively buggy within the Z80, it's possible that it was fixed in a later revision, so I grabbed the oldest CPU I could, which I extracted from a ZX81 issue one machine. Don't worry, it was temporary.


## Software

The test program is in [iffcheck.asm](iffcheck.asm). The idea is to execute an EI at address 200h so that the NMI is activated right after it ends, then execute a RETN within the interrupt handler, and then check if a maskable interrupt is triggered afterwards. If so, the real CPU behaves as expected, and the bug that is present in some simulations does not occur.

Since there is no RAM, the NMI interrupt service routine sets SP to point to ROM, specifically to an address containing the point where RETN should resume execution.

For further verification, some passpoints are placed that mark whether a certain point of the program was executed.

Output is done using the LED, by emitting flashes similar to Morse codes in trains of 8 pulses. A long pulse means a 1 and a short pulse means a 0. The bit position of the pulse determines the passpoint it belongs to. Bits are transmitted in big endian order, that is, from 7 (MSb) to 0 (LSb).


## Results

The result is that the CPU does not exhibit the buggy behaviour that some simulations do, meaning that IFF2 is not cleared when an NMI happens during the execution of EI, and hence the RETN activates maskable interrupts again. Here are the details:

Observed result: Bits 7, 6, 3, 1 and 0 were set; the others were cleared. This means:

- Bits set, in order of execution:
  - Bit 7: It executed the initialization.
  - Bit 0: It executed the instruction at 1FFh, right before asserting NMI.
  - Bit 3: It executed the NMI ISR.
  - Bit 1: It executed the 1st instruction of CheckInt.
  - Bit 6: It executed the INT routine (meaning EI at 200h was executed too, without clearing IFF2).
- Bits not set and their meaning:
  - Bit 5: It didn't execute the instruction after EI, which means that the NMI handler was executed between EI and the instruction that follows.
  - Bit 4: It didn't execute the 2nd instruction of CheckInt, because the maskable interrupt was triggered before that happened.
  - Bit 2: It's never set by the software so it means nothing.

At the same time, this test also proves the following (already known) fact: that if IFF1 is clear and IFF2 is set, when executing RETN, at least one more instruction will execute before the maskable interrupt is allowed to take place. All die simulations already match this behaviour anyway. The behaviour when IFF1 is set was not tested, because that would require a different hardware setup unless executing EI immediately followed by RETN, but EI clears IFF1 so it's not exactly the same test. Simulations allow the interrupt to happen right after RETN when IFF1 is set, no matter whether EI was the last one executed before RETN or not.


## Extra test - Software

The above hardware allows for another, simpler test which can also be performed on a machine such as the Spectrum, but since this was a testing hardware, we used it here anyway. The aim is to determine whether, when a maskable interrupt is triggered during execution of a LD A,I or LD A,R instruction, the resulting parity/overflow bit is set as it should. If not, that's a bug, as reported here: http://www.z80.info/z80bugs.htm

The software to perform this test is [iff2test.asm](iff2test.asm). It just does an EI followed by LD A,R, and the interrupt routine passes the resulting P/V flag to the LED.


## Extra test result

The result is that bit 5 of the LED stream is not set, which means that P/V was clear. Therefore, the bug is present.

I'm not good at writing ending words, so... well, there you go.
